home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3.2 / Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO / packet / n17jsrc / trace.c < prev    next >
C/C++ Source or Header  |  1991-04-30  |  8KB  |  331 lines

  1. /* Packet tracing - top level and generic routines, including hex/ascii
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. /* Mods by G1EMM */
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <time.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "iface.h"
  11. #include "pktdrvr.h"
  12. #include "commands.h"
  13. #include "config.h"
  14. #include "trace.h"
  15.  
  16. static void ascii_dump __ARGS((FILE *fp,struct mbuf **bpp));
  17. static void ctohex __ARGS((char *buf,int16 c));
  18. static void fmtline __ARGS((FILE *fp,int16 addr,char *buf,int16 len));
  19. static void hex_dump __ARGS((FILE *fp,struct mbuf **bpp));
  20. static void showtrace __ARGS((struct iface *ifp));
  21.  
  22. /* Redefined here so that programs calling dump in the library won't pull
  23.  * in the rest of the package
  24.  */
  25. static char nospace[] = "No space!!\n";
  26.  
  27. struct tracecmd Tracecmd[] = {
  28.     "input",    IF_TRACE_IN,    IF_TRACE_IN,
  29.     "-input",    0,        IF_TRACE_IN,
  30.     "output",    IF_TRACE_OUT,    IF_TRACE_OUT,
  31.     "-output",    0,        IF_TRACE_OUT,
  32.     "broadcast",    0,        IF_TRACE_NOBC,
  33.     "-broadcast",    IF_TRACE_NOBC,    IF_TRACE_NOBC,
  34.     "raw",        IF_TRACE_RAW,    IF_TRACE_RAW,
  35.     "-raw",        0,        IF_TRACE_RAW,
  36.     "ascii",    IF_TRACE_ASCII,    IF_TRACE_ASCII|IF_TRACE_HEX,
  37.     "-ascii",    0,        IF_TRACE_ASCII|IF_TRACE_HEX,
  38.     "hex",        IF_TRACE_HEX,    IF_TRACE_ASCII|IF_TRACE_HEX,
  39.     "-hex",        IF_TRACE_ASCII,    IF_TRACE_ASCII|IF_TRACE_HEX,
  40.     "off",        0,        0xffff,
  41.     NULLCHAR,    0,        0
  42. };
  43.  
  44.  
  45. void
  46. dump(iface,direction,type,bp)
  47. register struct iface *iface;
  48. int direction;
  49. unsigned type;
  50. struct mbuf *bp;
  51. {
  52. #ifdef TRACE
  53.     struct mbuf *tbp;
  54.     void (*func) __ARGS((FILE *,struct mbuf **,int));
  55.     int16 size;
  56.     time_t timer;
  57.     char *cp;
  58.  
  59.     if(iface == NULL || (iface->trace & direction) == 0)
  60.         return;    /* Nothing to trace */
  61.  
  62.     switch(direction){
  63.     case IF_TRACE_IN:
  64.         if((iface->trace & IF_TRACE_NOBC)
  65.          && (Tracef[type].addrtest != NULLFP)
  66.          && (*Tracef[type].addrtest)(iface,bp) == 0)
  67.             return;        /* broadcasts are suppressed */
  68.         time(&timer);
  69.         cp = ctime(&timer);
  70.         cp[24] = '\0';
  71.         fprintf(iface->trfp,"\n%s - %s recv:\n",cp,iface->name);
  72.         break;
  73.     case IF_TRACE_OUT:
  74.         time(&timer);
  75.         cp = ctime(&timer);
  76.         cp[24] = '\0';
  77.         fprintf(iface->trfp,"\n%s - %s sent:\n",cp,iface->name);
  78.         break;
  79.     }
  80.     if(bp == NULLBUF || (size = len_p(bp)) == 0){
  81.         fprintf(iface->trfp,"empty packet!!\n");
  82.         return;
  83.     }
  84.  
  85.     if(type < NCLASS)
  86.         func = Tracef[type].tracef;
  87.     else
  88.         func = NULLVFP;
  89.  
  90.     dup_p(&tbp,bp,0,size);
  91.     if(tbp == NULLBUF){
  92.         fprintf(iface->trfp,nospace);
  93.         return;
  94.     }
  95.     if(func != NULLVFP)
  96.         (*func)(iface->trfp,&tbp,1);
  97.     if(iface->trace & IF_TRACE_ASCII){
  98.         /* Dump only data portion of packet in ascii */
  99.         ascii_dump(iface->trfp,&tbp);
  100.     } else if(iface->trace & IF_TRACE_HEX){
  101.         /* Dump entire packet in hex/ascii */
  102.         free_p(tbp);
  103.         dup_p(&tbp,bp,0,len_p(bp));
  104.         if(tbp != NULLBUF)
  105.             hex_dump(iface->trfp,&tbp);
  106.         else
  107.             fprintf(iface->trfp,nospace);
  108.     }
  109.     free_p(tbp);
  110. #else
  111.     return;    /* Nothing to trace */
  112. #endif
  113. }
  114.  
  115. /* Dump packet bytes, no interpretation */
  116. void
  117. raw_dump(iface,direction,bp)
  118. struct iface *iface;
  119. int direction;
  120. struct mbuf *bp;
  121. {
  122.     struct mbuf *tbp;
  123.  
  124.     /* Dump entire packet in hex/ascii */
  125.     fprintf(iface->trfp,"\n******* raw packet dump (%s %s)\n",
  126.         ((direction & IF_TRACE_OUT) ? "send" : "recv"),iface->name);
  127.     dup_p(&tbp,bp,0,len_p(bp));
  128.     if(tbp != NULLBUF)
  129.         hex_dump(iface->trfp,&tbp);
  130.     else
  131.         fprintf(iface->trfp,nospace);
  132.     fprintf(iface->trfp,"*******\n");
  133.     free_p(tbp);
  134.     return;
  135. }
  136.  
  137. /* Dump an mbuf in hex */
  138. static void
  139. hex_dump(fp,bpp)
  140. FILE *fp;
  141. register struct mbuf **bpp;
  142. {
  143.     int16 n;
  144.     int16 address;
  145.     char buf[16];
  146.  
  147.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  148.         return;
  149.  
  150.     address = 0;
  151.     while((n = pullup(bpp,buf,sizeof(buf))) != 0){
  152.         fmtline(fp,address,buf,n);
  153.         address += n;
  154.     }
  155. }
  156. /* Dump an mbuf in ascii */
  157. static void
  158. ascii_dump(fp,bpp)
  159. FILE *fp;
  160. register struct mbuf **bpp;
  161. {
  162.     int c;
  163.     register int16 tot;
  164.  
  165.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  166.         return;
  167.  
  168.     tot = 0;
  169.     while((c = PULLCHAR(bpp)) != -1){
  170.         if((tot % 64) == 0)
  171.             fprintf(fp,"%04x  ",tot);
  172.         putc(isprint(uchar(c)) ? c : '.',fp);
  173.         if((++tot % 64) == 0)
  174.             fprintf(fp,"\n");
  175.     }
  176.     if((tot % 64) != 0)
  177.         fprintf(fp,"\n");
  178. }
  179. /* Print a buffer up to 16 bytes long in formatted hex with ascii
  180.  * translation, e.g.,
  181.  * 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?
  182.  */
  183. static void
  184. fmtline(fp,addr,buf,len)
  185. FILE *fp;
  186. int16 addr;
  187. char *buf;
  188. int16 len;
  189. {
  190.     char line[80];
  191.     register char *aptr,*cptr;
  192.     register char c;
  193.  
  194.     memset(line,' ',sizeof(line));
  195.     ctohex(line,(int16)hibyte(addr));
  196.     ctohex(line+2,(int16)lobyte(addr));
  197.     aptr = &line[6];
  198.     cptr = &line[55];
  199.     while(len-- != 0){
  200.         c = *buf++;
  201.         ctohex(aptr,(int16)uchar(c));
  202.         aptr += 3;
  203.         c &= 0x7f;
  204.         *cptr++ = isprint(uchar(c)) ? c : '.';
  205.     }
  206.     *cptr++ = '\n';
  207.     fwrite(line,1,(unsigned)(cptr-line),fp);
  208. }
  209. /* Convert byte to two ascii-hex characters */
  210. static void
  211. ctohex(buf,c)
  212. register char *buf;
  213. register int16 c;
  214. {
  215.     static char hex[] = "0123456789abcdef";
  216.  
  217.     *buf++ = hex[hinibble(c)];
  218.     *buf = hex[lonibble(c)];
  219. }
  220.  
  221. /* Modify or displace interface trace flags */
  222. int
  223. dotrace(argc,argv,p)
  224. int argc;
  225. char *argv[];
  226. void *p;
  227. {
  228.     struct iface *ifp;
  229.     struct tracecmd *tp;
  230.  
  231.     if(argc < 2){
  232.         for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  233.             showtrace(ifp);
  234.         return 0;
  235.     }
  236.     if((ifp = if_lookup(argv[1])) == NULLIF){
  237.         tprintf("Interface %s unknown\n",argv[1]);
  238.         return 1;
  239.     }
  240.     if(ifp->port){
  241.         tprintf("No trace on this interface - use master.\n");
  242.         return 1;
  243.     }
  244.     if(argc == 2){
  245.         showtrace(ifp);
  246.         return 0;
  247.     }
  248.     /* MODIFY THIS TO HANDLE MULTIPLE OPTIONS */
  249.     if(argc >= 3){
  250.         for(tp = Tracecmd;tp->name != NULLCHAR;tp++)
  251.             if(strncmp(tp->name,argv[2],strlen(argv[2])) == 0)
  252.                 break;
  253.         if(tp->name != NULLCHAR)
  254.             ifp->trace = (ifp->trace & ~tp->mask) | tp->val;
  255.         else
  256.             ifp->trace = htoi(argv[2]);
  257.     }
  258.     /* Always default to stdout unless trace file is given */
  259.     if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  260.         fclose(ifp->trfp);
  261.     ifp->trfp = stdout;
  262.     if(ifp->trfile != NULLCHAR)
  263.         free(ifp->trfile);
  264.     ifp->trfile = NULLCHAR;
  265.  
  266.     if(argc >= 4){
  267.         if((ifp->trfp = fopen(argv[3],APPEND_TEXT)) == NULLFILE){
  268.             tprintf("Can't write to %s\n",argv[3]);
  269.             ifp->trfp = stdout;
  270.         } else {
  271.             ifp->trfile = strdup(argv[3]);
  272.         }
  273.     }
  274.     showtrace(ifp);
  275.     return 0;
  276. }
  277. /* Display the trace flags for a particular interface */
  278. static void
  279. showtrace(ifp)
  280. register struct iface *ifp;
  281. {
  282.     if(ifp == NULLIF)
  283.         return;
  284.     tprintf("%s:",ifp->name);
  285.     if(ifp->port){
  286.         tprintf(" trace on master interface only.\n");
  287.         return;
  288.     }
  289.     if(ifp->trace & (IF_TRACE_IN | IF_TRACE_OUT | IF_TRACE_RAW)){
  290.         if(ifp->trace & IF_TRACE_IN)
  291.             tprintf(" input");
  292.         if(ifp->trace & IF_TRACE_OUT)
  293.             tprintf(" output");
  294.  
  295.         if(ifp->trace & IF_TRACE_NOBC)
  296.             tprintf(" - no broadcasts");
  297.  
  298.         if(ifp->trace & IF_TRACE_HEX)
  299.             tprintf(" (Hex/ASCII dump)");
  300.         else if(ifp->trace & IF_TRACE_ASCII)
  301.             tprintf(" (ASCII dump)");
  302.         else
  303.             tprintf(" (headers only)");
  304.  
  305.         if(ifp->trace & IF_TRACE_RAW)
  306.             tprintf(" Raw output");
  307.  
  308.         if(ifp->trfile != NULLCHAR)
  309.             tprintf(" trace file: %s",ifp->trfile);
  310.         tprintf("\n");
  311.     } else
  312.         tprintf(" tracing off\n");
  313. }
  314.  
  315. /* shut down all trace files */
  316. void
  317. shuttrace()
  318. {
  319.     struct iface *ifp;
  320.  
  321.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next){
  322.         if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  323.             fclose(ifp->trfp);
  324.         if(ifp->trfile != NULLCHAR)
  325.             free(ifp->trfile);
  326.         ifp->trfile = NULLCHAR;
  327.         ifp->trfp = NULLFILE;
  328.     }
  329. }
  330.  
  331.